<?php

/**
 * Vega Framework
 *
 * @url http://vega.com.vn
 * @url http://clip.vn
 */

/**
 * View class
 *
 * Vega Framework's presentation engine
 */

require_once 'Vega/View/Helper/Common.php';

class Vega_View
{

    /**
     * Data
     *
     * @var array
     */
    protected $_data = array();

    /**
     * Main template file
     *
     * @var string
     */
    protected $_templateFile = null;

    /**
     * Template dir
     *
     * @var string
     */
    protected $_templateDir = '/';

    /**
     * Layout dir
     *
     * @var string
     */
    protected $_layoutDir = '/';

    /**
     * Skin name
     *
     * @var string
     */
    protected $_skinName = 'default';

    /**
     * Name of the layout file
     *
     * @var string
     */
    protected $_layoutName = 'default';

    /**
     * The loader
     *
     * @var Vega_Loader
     */
    protected $_loader = null;

    protected static $_globalCacheManager = null;

    protected $_cacheManager = null;



    public static function setGlobalCacheManager($cache)
    {
        self::$_globalCacheManager = $cache;
    }

    public function setCacheManager($cache)
    {
        $this->_cacheManager = $cache;
        return $this;
    }

    public function getCacheManager()
    {
        return $this->_cacheManager;
    }

    /**
     * Constructor
     *
     * @param Vega_Loader $loader
     */
    public function __construct(Vega_Loader $loader)
    {
        $this->_cacheManager  = self::$_globalCacheManager;
        
        $this->_loader = $loader;

        // TODO improve this
        $this->_loader->setDir('element', 'elements')
                      ->setDir('helper', 'helpers');

    }


    /**
     * Get the skin directory.
     *
     * Skin dir = Layout dir + Skin name
     *
     * @return unknown
     */
    protected function _getSkinDir()
    {
        return $this->_layoutDir . DIRECTORY_SEPARATOR . $this->_skinName;
    }

    /**
     * Render main template file
     *
     * @param string $templateFile
     * @param array $options
     * @return string
     */
    public function renderTemplate($templateFile = null)
    {
        if (null == $templateFile)
        {
            $templateFile = $this->_templateFile;
        }

        return $this->render($templateFile, $this->_data);
    }

    /**
     * Renders layout
     *
     * @param string $content HTML string
     * @return unknown
     */
    public function renderLayout($content)
    {
        $layoutPath = $this->_getSkinDir() . DIRECTORY_SEPARATOR . $this->_layoutName . '.layout.php';

        $data = array_merge($this->_data, array('content' => $content));

        return $this->render($layoutPath, $data);
    }

    /**
     * Outputs rendered HTML
     *
     * @param string $templateFile
     * @return string
     */
    /*public function output($templateFile)
    {
        if (!$this->_loader->isAbsolutePath($templateFile))
        {
            $templateFile = $this->_templateDir . DIRECTORY_SEPARATOR . $templateFile . '.tpl.php';
        }

        $renderOptions = $layoutOptions = array();

        if (($this->getOption('cache_output', 0) > 0) && null != $this->_cacheManager)
        {

            $renderOptions['cache_name'] = $layoutOptions['cache_name'] = $this->_cacheManager->getPageCacheKey(
                    $this->getOption('cache_prefix', null)
            );

            if ($this->getOption('cache_no_layout', false))
            {
                $layoutOptions['cache'] = 0;
                $renderOptions['cache'] = $this->getOption('cache_output');
                $renderOptions['cache_options']['no_layout']   = true ;
                $renderOptions['cache_options']['skin_name']   = $this->getSkinName();
                $renderOptions['cache_options']['layout_name'] = $this->getLayoutName();
                $renderOptions['cache_options']['layout_dir']  = $this->getLayoutDir();
            }
            else
            {
                $layoutOptions['cache'] = $this->getOption('cache_output');
                $renderOptions['cache'] = 0;
            }
        }

        $content = $this->render($templateFile, $this->_data, $renderOptions);

        if ($this->getOption('auto_render_layout', true) && $this->getOption('use_layout', true))
        {
            $content = $this->renderLayout($content, $layoutOptions);
        }

        return $content;
    }*/

    /**
     * Sets template file
     *
     * @param string $templateFile
     * @return Vega_View
     */
    public function setTemplateFile($templateFile)
    {
        $this->_templateFile = $templateFile;
        return $this;
    }

    /**
     * Return template file
     *
     * @return string
     */
    public function getTemplateFile()
    {
        return $this->_templateFile;
    }

    /**
     * Sets template directory path
     *
     * @param  string $dir
     * @return Vega_View
     */
    public function setTemplateDir($dir)
    {
        $this->_templateDir = $dir;
        return $this;
    }

    public function getTemplateDir()
    {
        return $this->_templateDir;
    }

    /**
     * Sets layout directory path
     *
     * @param string $dir
     * @return Vega_View
     */
    public function setLayoutDir($dir)
    {
        $this->_layoutDir = $dir;
        return $this;
    }

    public function getLayoutDir()
    {
        return $this->_layoutDir;
    }


    /**
     * Sets skin name
     *
     * @param string $name
     * @return Vega_View
     */
    public function setSkinName($name)
    {
        $this->_skinName = $name;
        return $this;
    }

    public function getSkinName()
    {
        return $this->_skinName;
    }



    /**
     * Sets layout name
     *
     * @param string $layout
     * @return Vega_View
     */
    public function setLayoutName($layout)
    {
        $this->_layoutName = $layout;
        return $this;
    }

    public function getLayoutName()
    {
        return $this->_layoutName;
    }

    /**
     * Assigns a variable to view data stack
     *
     * @param string $name
     * @param mixed $value
     * @return Vega_View
     */
    public function assign($name, $value)
    {
        $this->_data[$name] = $value;
        return $this;
    }

    /**
     * Render a template file
     *
     * @param string $templateFile Absolute file path of the template file
     * @param array $data
     * @return string
     */
    public function render($templateFile, &$data)
    {
        if (!$this->_loader->isAbsolutePath($templateFile))
        {
            $templateFile = $this->_templateDir . DIRECTORY_SEPARATOR . $templateFile . '.tpl.php';
        }

        return $this->_render($templateFile, $data);
    }

    /**
     * Renders a template file
     *
     * @param string $templateFile
     * @param array $data
     * @return string
     */
    protected function _render($templateFile, &$data)
    {
        if (!file_exists($templateFile) || !is_readable($templateFile))
        {
            require_once 'Vega/View/Exception.php';
            throw new Vega_View_Exception('The template file (' . $templateFile . ') does not exist');
        }

        extract($data);

        ob_start();
        ob_implicit_flush(false);
        include $templateFile;
        $content = ob_get_clean();
        return $content;
    }

    /**
     * Render a skin element.
     * This is the replacment for renderGlobalTemplate.
     *
     * @param string $template
     * @param string $data
     * @return string
     */
    public function renderSkinElement($template, $data = array(), $options = array())
    {

        $filepath = $this->_getSkinDir() . DIRECTORY_SEPARATOR . $template . '.tpl.php';

        return $this->render($filepath, $data, $options);
    }

    /**
     * Render a skin element.
     *
     * This is the old way. Not recommended since 1.1.
     * This is still here because of the compatibility with the old codes.
     *
     * @param string $template
     * @param string $data
     * @return string
     */
    public function renderGlobalTemplate($template, $data = array(), $options = array())
    {
        return $this->renderSkinElement($template, $data, $options);
    }


    /**
     * Renders a template element.
     * This is the recommended way to render a template element since version 1.1
     *
     * @param unknown_type $template
     * @param unknown_type $data
     * @return unknown
     */
    public function renderElement($template, $data = array(), $options = array())
    {
        $filepath = $this->_loader->getPath('element', $template);
        return $this->render($filepath, $data, $options);
    }

    /**
     * Excute a widget from template script
     *
     * @param string $name
     * @param array $options
     * @return string
     */
    public function executeWidget($name, array $params = array(), $options = array())
    {
        $cache     = (isset($options['cache']) ? $options['cache'] : 0);

        if ($cache > 0 && (null != $this->_cacheManager))
        {
            $cacheName = $name . '_widget';
            
            if (isset($options['cache_prefix']))
            {
                $this->_cacheManager->setPrefix($options['cache_prefix']);
            }

            $cacheData = $this->_cacheManager->load($cacheName);

            if ($cacheData)
            {
                return $cacheData;
            }

            $widget = Vega_App::getInstance()->loadWidget($name, $params);

            if (!$widget)
            {
                return false;
            }

            $out = $widget->run();
            
            $result = $this->_cacheManager->save($cacheName, $out, $cache);
        }
        else
        {
            $widget = Vega_App::getInstance()->loadWidget($name, $params);
            if (!$widget)
            {
                return false;
            }
            $out = $widget->run();
        }
        return $out;
    }

    /**
     * Loads a helper
     *
     * @param unknown_type $name
     */
    public function loadHelper($name)
    {
        $this->_loader->load('helper', $name . '.helper.php');
    }
}

